package ccm.component.menu;

import ccm.common.Buffer;
import ccm.common.CCMConfigManager;
import ccm.common.Pair;
import ccm.component.override.DefaultComboBoxModel;
import ccm.component.override.JButton;
import ccm.component.override.JComboBox;
import ccm.component.override.JLabel;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;

class EnumMenuItemJPanel extends SingleMenuItem implements ActionListener, ExRequestDataInterface, ValuableMenuItem
{
    final protected JLabel valueJLabel;
    final protected JComboBox<String> valueJComboBox;
    final protected JButton sendJButton;
    final ccm.component.override.DefaultComboBoxModel<String> model;
    protected Integer value;

    protected EnumMenuItemJPanel(DelegateSenderInterface sender,Component[] rightMenu,String saveArgPrefix,int dataIndex,boolean canModify,ScnsType type,int page,String name,int itemLength)
    {
        super(sender,rightMenu,saveArgPrefix,dataIndex,canModify,type,page,name);
        valueJLabel=new JLabel();
        valueJLabel.setOpaque(true);
        add(valueJLabel);
        model=new DefaultComboBoxModel<String>(new String[itemLength]);
        valueJComboBox=new JComboBox<String>(model);
        add(valueJComboBox);
        valueJComboBox.addActionListener(this);
        sendJButton=new JButton("发送");
        add(sendJButton);
        sendJButton.addActionListener(this);
        loadConfig();
        setCanModify(canModify);
        Dimension dimension=new Dimension(100,(int)(valueJLabel.getFont().getSize()*1.2+10));
        valueJLabel.setPreferredSize(dimension);
        //valueJComboBox.setPreferredSize(dimension);
        valueJLabel.setBorder(BorderFactory.createEtchedBorder());
        valueJComboBox.setBorder(BorderFactory.createEtchedBorder());
        valueJComboBox.addActionListener(e->
        {
            if(!needExRequest())
            {
                storeConfig();
            }
        });
    }

    @Override
    public void setCanModify(boolean canModify)
    {
        super.setCanModify(canModify);
        if(valueJComboBox!=null)
        {
            valueJComboBox.setVisible(canModify);
        }
        if(sendJButton!=null)
        {
            sendJButton.setVisible(canModify);
        }
    }

    @Override
    protected String storeConfig()
    {
        final String prefix=super.storeConfig();
        CCMConfigManager.setInteger(prefix+"/value",valueJComboBox.getSelectedIndex());
        return prefix;
    }

    @Override
    public String loadConfig()
    {
        final String prefix=super.loadConfig();
        if(valueJComboBox!=null)
        {
            valueJComboBox.setSelectedIndex(CCMConfigManager.setIntegerIfAbsent(prefix+"/value",0));
            updateColor();
        }
        return prefix;
    }

    protected void updateColor()
    {
        if(isCanModify()&&!sameAsValue(valueJComboBox.getSelectedIndex()))
        {
            valueJLabel.setForeground(Color.RED);
        }
        else
        {
            valueJLabel.setForeground(null);
        }
    }

    protected boolean sameAsValue(Object v)
    {
        return Objects.equals((Integer)v,value);
    }

    public static Pair<Object,Integer> decodeInnerDataEx(byte[] receiveBuf,int start)
    {
        return new Pair<>(Buffer.getInt32(receiveBuf,start),start+4);
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        updateColor();
        if(e.getSource()==sendJButton||autoSendJCheckBox.isSelected())
        {
            needSendValueFlag=true;
        }
    }

    @Override
    public void exRequestData(UpdateAndSleep updateAndSleep) throws InterruptedException
    {
        for(int round=0;round<model.getSize();round+=1)
        {
            System.out.println(dataIndex+"exRequestData"+round);
            int start=0;
            byte[] buf=new byte[64];
            start=Buffer.setUint16(buf,start,dataIndex);
            start=Buffer.setUint8(buf,start,type.ordinal());
            start=Buffer.setInt32(buf,start,round);
            addTailAndSend(buf,start,0X22);
            updateAndSleep.updateAndSleep();
        }
    }

    @Override
    public void decodeExAndSet(byte[] receiveBuf,int start,int len)
    {
        final int round=Buffer.getInt32(receiveBuf,start);
        final String str=Buffer.getString(receiveBuf,start+4,len-4);
        System.out.println(dataIndex+"setExData"+round+" "+str);
        model.replaceElementAt(str,round);
        if(value!=null)
        {
            valueJLabel.setText(model.getElementAt(value));
        }
        valueJComboBox.revalidate();
        valueJComboBox.repaint();
    }

    @Override
    public boolean needExRequest()
    {
        for(int i=0;i<model.getSize();++i)
        {
            if(null==model.getElementAt(i)||"".equals(model.getElementAt(i)))
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public void decodeValueAndSet(byte[] receiveBuf,int start)
    {
        Integer value=Buffer.getInt32(receiveBuf,start);
        if(this.value==null||!sameAsValue(value))
        {
            valueJLabel.setBackground(Color.YELLOW);
        }
        else
        {
            valueJLabel.setBackground(null);
        }
        this.value=value;
        valueJLabel.setText(model.getElementAt(value));
        updateColor();
    }

    @Override
    public void loadValueToInput()
    {
        valueJComboBox.setSelectedIndex(value);
        updateColor();
        storeConfig();
    }

    @Override
    public void sendValueToDevice()
    {
        int start=0;
        byte[] buf=new byte[64];
        start=Buffer.setUint16(buf,start,dataIndex);
        start=Buffer.setUint8(buf,start,type.ordinal());
        start=Buffer.setInt32(buf,start,valueJComboBox.getSelectedIndex());
        addTailAndSend(buf,start,0X20);
        needSendValueFlag=false;
    }

    @Override
    public void requestValue()
    {
        System.out.println("requestValue(0X1E) "+dataIndex);
        int start=0;
        byte[] buf=new byte[64];
        start=Buffer.setUint16(buf,start,dataIndex);
        addTailAndSend(buf,start,0X1E);
    }

    @Override
    public String toString()
    {
        return model.getElementAt(value);
    }
}
